package com.finddeer.bookkeeping;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.finddeer.bookkeeping.database.BillBaseHelper;
import com.finddeer.bookkeeping.database.BillCursorWrapper;
import com.finddeer.bookkeeping.database.BillDbSchema.BillTable;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;


/**
 * author    : leaves
 * gitee     : https://gitee.com/LEAVES2018
 * time      : 2018/12/23 10:30 PM
 * function  : 账单的单例类型，负责账单的增删改查
 */
public class BillLab {

    private static BillLab sBillLab;    //  单例对象

    private Context mContext;
    private SQLiteDatabase mDatabase;   //  SQLite数据库

    public static BillLab get(Context context) {
        if (sBillLab == null) {
            sBillLab = new BillLab(context);
        }
        return sBillLab;
    }   //  获取单例方法

    private BillLab(Context context) {
        mContext = context.getApplicationContext();
        mDatabase = new BillBaseHelper(mContext).getWritableDatabase();
        //  （1）打开billBase.db数据库；如果不存在，就先创建billBase.db数据库文件
        //  （2）如果是首次创建数据库，就调用onCreate(SQLiteDatabase)方法，然后保存最新的版本号
        //  （3）如果已创建过数据库，首先检查它的版本号。如果BillBaseHelper中的版本号更高，就调用onUpgrade(SQLiteDatabase, int, int)方法升级

    }   //  私有构造方法，由get方法调用。创建或者打开数据库，并检查更新。

    public void addBill(Bill bill) {
        ContentValues values = getContentValues(bill);
        mDatabase.insert(BillTable.NAME, null, values);
        //  第一个参数是数据表名，第三个是要写入的数据；第二个参数nullColumnHack可以忽略ContentValues空值……
    }   //  向数据库中插入新bill

    public void updateBill(Bill bill) {
        String uuidString = bill.getId().toString();
        ContentValues values = getContentValues(bill);
        //  update(String, ContentValues, String, String[])方法类似于insert(...)方法
        //  向其传入要更新的数据表名和为表记录准备的ContentValues
        //  不同的是，需要确定该更新哪些记录，然后指定where子句中的参数值
        mDatabase.update(BillTable.NAME, values, BillTable.Cols.UUID + " = ?",
                new String[] { uuidString });
        //  避免SQL脚本注入，使用?
    }   //  更改数据

    private BillCursorWrapper queryBills(String whereClause, String[] whereArgs) {
        Cursor cursor = mDatabase.query(
                BillTable.NAME, //  要查询的数据表
                null,   //  指定要依次获取哪些字段的值
                whereClause,    //  插入的位置
                whereArgs,      //  插入的数据
                null,
                null,
                null
        );

        return new BillCursorWrapper(cursor);
    }   //  查找

    public void deleteBill(Bill bill) {
        mDatabase.delete(BillTable.NAME, "uuid = ?", new String[] {String.valueOf(bill.getId())});
        //  用uuid判断删除哪一项
    }   //  删除bill，用id判断

    public List<Bill> getBills() {
        List<Bill> bills = new ArrayList<>();

        BillCursorWrapper cursor = queryBills(null, null);

        try {
            cursor.moveToFirst();
            while (!cursor.isAfterLast()) {
                bills.add(cursor.getBill());
                cursor.moveToNext();
            }
        } finally {
            cursor.close();
        }
        return bills;
    }   //  获取SQLite数据库中存储的所有bill

    public Bill getBill(UUID id) {
            BillCursorWrapper cursor = queryBills(BillTable.Cols.UUID + " = ?",
                    new String[] { id.toString() }
                    );
            try {
                if (cursor.getCount() == 0) {
                    return null;
                }

                cursor.moveToFirst();
                return cursor.getBill();
            } finally {
                cursor.close();
            }
    }   //  根据id在SQLite数据库中查找并返回bill

    private static ContentValues getContentValues(Bill bill) {
        ContentValues values = new ContentValues();
        values.put(BillTable.Cols.UUID, bill.getId().toString());
        values.put(BillTable.Cols.TITLE, bill.getTitle());
        values.put(BillTable.Cols.AMOUNT, bill.getAmount()+"");
        values.put(BillTable.Cols.TAG, bill.getTag());
        values.put(BillTable.Cols.DATE, bill.getDate().getTime());
        values.put(BillTable.Cols.LOCALE, bill.getLocale());
        return values;
    }   //  负责处理数据库写入和更新操作的辅助类
        //  键值存储类，类似于HashMap和Bundle
        //  只能用于处理SQLite数据
        //  ContentValues的键就是数据表字段
}
